#include "LocalRegression.h"
#include "KNode.h"
#include <math.h>

#ifdef _DEBUG
   #define new MYDEBUG_NEW
#endif

//-------------------------begin LocalAverager---------------------------------
namespace kdtree
{
void LocalAverager::reset()
{
	max = -9999; 
	min = 9999; 
	mean = 0; 
	size = 0; 
}

LocalAverager::LocalAverager(KNode* parent, int d)
	:LocalRegression(parent, d)
{
	reset(); 
}

 double LocalAverager::addData( KData & pt)
{
	if (pt.second > max)
		max = pt.second; 

	if (pt.second < min)
		min = pt.second; 

	mean = ((mean*size) + pt.second )/ (size+1); 
	size++; 
	return computeError(); 

}

double LocalAverager::computeError()
{
	double err = fabs(max - mean); 
	if (fabs(min - mean) > err)
		err = fabs(min-mean); 

	return err; 

}

double LocalAverager::addData(list<KData>& pts, list<KData>::iterator startIndex)
{
	double sum = mean*size; 

	for(list<KData>::iterator it = startIndex; it != pts.end(); it++)
	{
		if ((*it).second > max)
			max = (*it).second; 

		if ((*it).second < min)
			min = (*it).second; 

		sum += (*it).second ; 
		size++; 
	}
	mean = sum/size; 

	return computeError(); 
}

inline double LocalAverager::kernelize(double input)
{
	return expf(- input*input); 
}

inline double LocalAverager::distance(Observation o1, Observation o2) 
{
	double result = 0; 
	for(int i=0; i< dim; i++)
	{
		double tmp = (o1[i]-o2[i]); 
		result += tmp*tmp; 
	}
	
	return sqrtf(result); 
}


double LocalAverager::predict(Observation o)
{
	//warning: using nodes data to compute weighted average instead of a simple mean
  
 	if (m_parent->points.empty())
		return 0; 

	const double bandwidth = 40; 
	double result = 0; 
	int size = m_parent->points.size(); 
	double denom=0; 
	for(list<KData>::iterator it= m_parent->points.begin(); it!= m_parent->points.end(); it++)
	{
		double w= distance(o,(*it).first)/bandwidth; 
		w = kernelize(w); 
		denom += w; 
		result += w*(*it).second; 			
	}

	result /= denom; 
	return result; 
  
	return mean; 
}

}//namespace
//-----------------end LocalAverager --------------------------------


